package org.pie.drawing.apps.picimageserver.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.pie.drawing.apps.picimageserver.common.exception.ApiException;
import org.pie.drawing.apps.picimageserver.dto.ImageInfoDto;
import org.pie.drawing.apps.picimageserver.dto.ImageSearchDTO;
import org.pie.drawing.apps.picimageserver.entity.ImageIndexEntity;
import org.pie.drawing.apps.picimageserver.mapper.ImageIndexMapper;
import org.pie.drawing.apps.picimageserver.service.ImageIndexService;
import org.pie.drawing.apps.picimageserver.utils.DownloadUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ImageIndexServiceImpl extends ServiceImpl<ImageIndexMapper, ImageIndexEntity> implements ImageIndexService {

    @Value("${pic.image_root_path}")
    private String imageRootPath;

    @Override
    @Async("customTaskExecutor")
    public void saveImageIndex(ImageInfoDto dto) {
        String productCode = dto.getProductCode();
        String productTime = dto.getProductTime();

        if (StrUtil.isBlank(productTime)) {
            throw new ApiException("图片保存失败，产品时间为空");
        }

        Date productDate = DateUtil.parse(productTime);
        int hour = DateUtil.hour(productDate, true);
        String hourStr = StrUtil.fillBefore(String.valueOf(hour), '0', 2);

        ImageIndexEntity entity = new ImageIndexEntity();

        this.handleProductCode(entity, productCode);
        entity.setProductTime(productDate);
        entity.setHour(hourStr);
        entity.setAgeing(dto.getAgeing());

        String imagePath = this.buildImageAbsolutePath(entity);
        FileUtil.writeBytes(Base64.decode(dto.getImageBase64Str()), imagePath);
        entity.setImagePath(imagePath);

        ImageIndexEntity oldEntity = this.getOne(new LambdaQueryWrapper<ImageIndexEntity>().eq(ImageIndexEntity::getImagePath, imagePath));
        if (null == oldEntity) {
            save(entity); // 新增
        } else {
            // 更新
            entity.setId(oldEntity.getId());
            this.updateById(entity);
        }
    }

    @Override
    public void searchImageIndex(ImageSearchDTO dto, HttpServletResponse response) {
        String flag1 = dto.getFlag1();
        String flag2 = dto.getFlag2();
        String flag3 = dto.getFlag3();
        String productStartTime = dto.getProductStartTime();
        String productEndTime = dto.getProductEndTime();
        String hour = dto.getHour();
        String ageing = dto.getAgeing();
        List<ImageIndexEntity> list = this.list(new LambdaQueryWrapper<ImageIndexEntity>()
                .eq(StrUtil.isNotBlank(flag1), ImageIndexEntity::getFlag1, flag1)
                .eq(StrUtil.isNotBlank(flag2), ImageIndexEntity::getFlag2, flag2)
                .eq(StrUtil.isNotBlank(flag3), ImageIndexEntity::getFlag3, flag3)
                .ge(StrUtil.isNotBlank(productStartTime), ImageIndexEntity::getProductTime, productStartTime)
                .lt(StrUtil.isNotBlank(productEndTime), ImageIndexEntity::getProductTime, productEndTime)
                .eq(StrUtil.isNotBlank(hour), ImageIndexEntity::getHour, hour)
                .eq(StrUtil.isNotBlank(ageing), ImageIndexEntity::getAgeing, ageing)
                .last("limit 1")
        );
        ImageIndexEntity entity = null;
        if (CollUtil.isNotEmpty(list)) {
            entity = list.get(0);
        }
        if (null == entity) {
            throw new ApiException("查询结果为空");
        }
        String imagePath = entity.getImagePath();
        if (!FileUtil.exist(imagePath)) {
            throw new ApiException("产品不存在");
        }

        DownloadUtil.download(imagePath, response);
    }

    @Override
    public void searchById(Long id, HttpServletResponse response) {
        ImageIndexEntity entity = this.getById(id);
        if (null == entity) {
            throw new ApiException("查询结果为空");
        }
        String imagePath = entity.getImagePath();
        if (!FileUtil.exist(imagePath)) {
            throw new ApiException("产品不存在");
        }
        DownloadUtil.download(imagePath, response);
    }

    @Override
    public List<ImageIndexEntity> list(ImageSearchDTO dto) {
        String flag1 = dto.getFlag1();
        String flag2 = dto.getFlag2();
        String flag3 = dto.getFlag3();
        String productStartTime = dto.getProductStartTime();
        String productEndTime = dto.getProductEndTime();
        String hour = dto.getHour();
        String ageing = dto.getAgeing();
        return this.list(new LambdaQueryWrapper<ImageIndexEntity>()
                .eq(StrUtil.isNotBlank(flag1), ImageIndexEntity::getFlag1, flag1)
                .eq(StrUtil.isNotBlank(flag2), ImageIndexEntity::getFlag2, flag2)
                .eq(StrUtil.isNotBlank(flag3), ImageIndexEntity::getFlag3, flag3)
                .ge(StrUtil.isNotBlank(productStartTime), ImageIndexEntity::getProductTime, productStartTime)
                .lt(StrUtil.isNotBlank(productEndTime), ImageIndexEntity::getProductTime, productEndTime)
                .eq(StrUtil.isNotBlank(hour), ImageIndexEntity::getHour, hour)
                .eq(StrUtil.isNotBlank(ageing), ImageIndexEntity::getAgeing, ageing)
                .orderByAsc(ImageIndexEntity::getProductTime, ImageIndexEntity::getHour, ImageIndexEntity::getAgeing)
        );
    }

    @Override
    public ImageIndexEntity newestImage(ImageSearchDTO dto) {
        String flag1 = dto.getFlag1();
        String flag2 = dto.getFlag2();
        String flag3 = dto.getFlag3();
        List<ImageIndexEntity> list = this.list(new LambdaQueryWrapper<ImageIndexEntity>()
                .eq(StrUtil.isNotBlank(flag1), ImageIndexEntity::getFlag1, flag1)
                .eq(StrUtil.isNotBlank(flag2), ImageIndexEntity::getFlag2, flag2)
                .eq(StrUtil.isNotBlank(flag3), ImageIndexEntity::getFlag3, flag3)
                .orderByDesc(ImageIndexEntity::getProductTime)
                .last("limit 1")
        );
        if (CollUtil.isEmpty(list)) {
            throw new ApiException("产品不存在");
        }
        return list.get(0);
    }

    @Override
    public List<String> hourList(ImageSearchDTO dto) {
        return this.baseMapper.hourList(dto);
    }

    private void handleProductCode(ImageIndexEntity entity, String productCode) {
        if (StrUtil.isBlank(productCode)) {
            throw new ApiException("图片保存失败，产品编码为空");
        }
        List<String> productCodeList = StrUtil.split(productCode, "#");
        int size = productCodeList.size();
        if (size >= 1) {
            entity.setFlag1(productCodeList.get(0));
        }
        if (size >= 2) {
            entity.setFlag2(productCodeList.get(1));
        }
        if (size >= 3) {
            entity.setFlag3(productCodeList.get(2));
        }
    }

    private String buildImageAbsolutePath(ImageIndexEntity entity) {
        String flag1 = entity.getFlag1();
        String flag2 = entity.getFlag2();
        String flag3 = entity.getFlag3();
        String imagePath = imageRootPath;
        if (StrUtil.isNotBlank(flag1)) {
            imagePath = imagePath + flag1 + "/";
        }
        if (StrUtil.isNotBlank(flag2)) {
            imagePath = imagePath + flag2 + "/";
        }
        if (StrUtil.isNotBlank(flag3)) {
            imagePath = imagePath + flag3 + "/";
        }
        Date productTime = entity.getProductTime();
        int year = DateUtil.year(productTime);
        imagePath = imagePath + year + "/";
        String dayStr = DateUtil.format(productTime, "yyyyMMddHH");
        imagePath = imagePath + dayStr + "/";
        if (!FileUtil.exist(imagePath)) {
            FileUtil.mkdir(imagePath);
        }

        String ageing = entity.getAgeing();
        if (StrUtil.isNotBlank(ageing)) {
            imagePath = imagePath + dayStr + "_" + ageing + ".png";
        } else {
            imagePath = imagePath + dayStr + ".png";
        }
        return imagePath;
    }
}
